package cn.scy.business.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.scy.base.PageParam;
import cn.scy.base.PageResult;
import cn.scy.business.domain.entity.SysUser;
import cn.scy.business.domain.param.ChangePwdParam;
import cn.scy.business.domain.param.LoginParam;
import cn.scy.business.domain.vo.SysUserVO;
import cn.scy.business.mapper.SysUserMapper;
import cn.scy.exception.BusinessException;
import cn.scy.util.JbcryptUtils;
import cn.scy.util.PageUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 用户相关服务
 *
 * @author scy
 */
@Service
public class UserLoginService {

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private GetTokenService getTokenService;

    public boolean checkToken(String uuToken) {
        Claims claims = Jwts.parser().setSigningKey("yunqi").parseClaimsJws(uuToken).getBody();
        String id = (String) claims.get("id");
        SysUser sysUser = sysUserMapper.selectById(id);
        if (StrUtil.equals(sysUser.getAccessToken(), "null")) {
            return false;
        }
        return StrUtil.equals(sysUser.getAccessToken(), uuToken);
    }

    public boolean checkPasswd(LoginParam loginParam) {
        SysUser sysUser = sysUserMapper.selectOne(
                Wrappers.<SysUser>lambdaQuery()
                        .eq(SysUser::getLoginId, loginParam.getLoginId())
        );
        return JbcryptUtils.checkPwd(loginParam.getPasswd(), sysUser.getPasswd());
    }

    public String login(LoginParam loginParam) {
        SysUser sysUser = sysUserMapper.selectOne(
                Wrappers.<SysUser>lambdaQuery()
                        .eq(SysUser::getLoginId, loginParam.getLoginId())
        );
        if (sysUser == null) {
            return null;
        }
        String token = createToken(sysUser.getId());
        sysUser.setAccessToken(token);
        sysUserMapper.updateById(sysUser);
        return token;
    }

    public boolean loginOut(String userId) {
        SysUser sysUser = sysUserMapper.selectById(userId);
        sysUser.setAccessToken("null");
        return sysUserMapper.updateById(sysUser) == 1;
    }

    private String createToken(String userId) {
        Date date = DateUtil.date();
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT") // 设置header
                .setHeaderParam("alg", "HS256").setIssuedAt(date) // 设置签发时间
                .setExpiration(new Date(date.getTime() + 1000 * 60 * 60 * 24)) // 设置过期时间
                .claim("id", String.valueOf(userId)) // 设置内容
                .setIssuer("yunqi") // 设置签发人
                .signWith(signatureAlgorithm, "yunqi"); // 签名，需要算法和key
        return builder.compact();
    }

    /**
     * 分页查询
     *
     * @param pageParam 分页参数
     * @return 分页结果
     */
    public PageResult<SysUserVO> listPage(PageParam pageParam) {
        Page<SysUser> pageQuery = PageUtil.convert2PageQuery(pageParam);
        Page<SysUser> pageSource = sysUserMapper.selectPage(
                pageQuery,
                Wrappers.<SysUser>lambdaQuery()
                        .orderByAsc(SysUser::getSort)
        );
        return PageUtil.convert2PageResult(pageSource, pageSource.getRecords(), SysUserVO.class);
    }

    /**
     * 修改密码
     *
     * @param changePwdParam 修改密码参数
     * @param request        请求对象
     * @return 修改密码结果
     */
    public Boolean changePwd(ChangePwdParam changePwdParam, HttpServletRequest request) {
        if (StrUtil.equals(changePwdParam.getOldPwd(), changePwdParam.getNewPwd())) {
            throw new BusinessException("新密码和旧密码不能相同");
        }
        if (changePwdParam.getNewPwd().length() < 6) {
            throw new BusinessException("密码不能少于6位字符");
        }
        String userId = getTokenService.getUserIdByToken(request);
        SysUser sysUser = sysUserMapper.selectById(userId);
        if (!JbcryptUtils.checkPwd(changePwdParam.getOldPwd(), sysUser.getPasswd())) {
            throw new BusinessException("旧密码不正确");
        }
        String hashed = JbcryptUtils.hashed(changePwdParam.getNewPwd());
        sysUser.setPasswd(hashed);
        return sysUserMapper.updateById(sysUser) == 1;
    }

    /**
     * 重置密码
     *
     * @param id 用户ID
     * @return 重置密码结果
     */
    public Boolean resetPwd(String id) {
        String hashed = JbcryptUtils.hashed("123456");
        SysUser sysUser = new SysUser();
        sysUser.setId(id);
        sysUser.setPasswd(hashed);
        return sysUserMapper.updateById(sysUser) == 1;
    }

}
